package doms


class Attribute(var name: String, var value: String?) {
    override fun toString(): String {
        if (value == null) {
            return name;
        }
        return """$name="$value" """
    }
}

open class Tag(var name: String, private var content: String = "") {
    val children: MutableList<Tag> = ArrayList()
    val attributes: MutableList<Attribute> = ArrayList()
    override fun toString(): String {
        if (this.name.isEmpty()) {
            return content;
        }

        var atr = attributes.joinToString(separator = " ")

        if( attributes.any()){
            atr = " " + atr;
        }

        if (this.children.isEmpty() && content.isEmpty()) {
            return "<$name${atr}/>"
        }

        return """<$name${atr}>
${content}${children.joinToString(separator = "\n")}
</$name>"""
    }
}


fun <T : Tag> Tag.doInit(tag: T, init: T.() -> Unit): T {
    tag.init()
    children.add(tag)
    return tag
}

//fun <T : Tag> Tag.doInit2(tag: T, init: T.() -> String): T {
//    tag.init()
//    children.add(tag)
//    return tag
//}


fun <T : Tag> Tag.doInit(tag: T): T {
    children.add(tag)
    return tag
}

fun <T : Tag> T.text(content: String): T {
    this.children.add(Text(content))
    return this
}

fun <T : Tag> T.set(name: String, value: String? = null): T {
    attributes.add(Attribute(name, value))
    return this
}


class Text(val text: String) : Tag("", text)

class Html : Tag("html") {
    fun head(title: String = "", init: Head.() -> Unit) {
        var head = Head();
        if( title.isNotEmpty()) {
            head.doInit(Title().text(title))
        }
        doInit(head, init)
    }
    fun body(init: Body.() -> Unit) = this.doInit(Body(), init)
}

open class RootElement(name: String) : Tag(name) {
    fun h1(init: () -> String) = doInit(H1().text(init()))
    fun h2(init: () -> String) = doInit(H2().text(init()))
    fun h3(init: () -> String) = doInit(H3().text(init()))

    fun p(init: () -> String) = doInit(P().text(init()))
    fun label(init: () -> String) = doInit(Label().text(init()))
    fun font(init: () -> String) = doInit(Font().text(init()))
    fun code(init: () -> String) = doInit(Code().text(init()))
    fun textarea(init: () -> String) = doInit(TextArea().text(init()))
    fun input(init: () -> String) = doInit(Input().text(init()))
    fun button(init: () -> String) = doInit(Button().text(init()))

    fun div(init: Div.() -> Unit) = doInit(Div(), init)
    fun span(init: Span.() -> Unit) = doInit(Span(), init)
    fun pre(init: Pre.() -> Unit) = doInit(Pre(), init)
    fun ul(init: Ul.() -> Unit) = doInit(Ul(), init)
    fun table(init: Table.() -> Unit) = doInit(Table(), init)
}

class Body : RootElement("body") {

}

class Head : Tag("head") {
    fun meta(name: String, content: String) = doInit(Meta()) { this.set("name", name).set(content) }
    fun style(init: () -> String) = this.doInit(Style().text(init()))
    fun script(init: () -> String) = doInit(Script().text(init()))
}

class Title() : Tag("title")
class Meta : Tag("meta")
class Script() : Tag("script")
class Style() : Tag("style")

class Table : Tag("table") {
    fun thead(init: Thead.() -> Unit) = doInit(Thead(), init)
    fun tbody(init: Tbody.() -> Unit) = doInit(Tbody(), init)
}

open class TableElement(name: String) : Tag(name) {
    fun tr(init: Tr.() -> Unit) = doInit(Tr(), init)
}

class Thead : TableElement("thead")
class Tbody : TableElement("tbody")
class Th : Tag("th")
class Tr : Tag("tr") {
    fun th(init: Th.() -> Unit) = doInit(Th(), init)
    fun td(init: Td.() -> Unit) = doInit(Td(), init)
}

class Td : RootElement("td")

class P() : Tag("p")
class H1() : Tag("h1")
class H2() : Tag("h2")
class H3() : Tag("h3")
class Div() : RootElement("div")
class Span() : RootElement("span")
class Button() : Tag("button")
class Input : Tag("input")
class Ul : Tag("ul") {
    fun li(init: Li.() -> Unit) = doInit(Li(), init)
}

class Li : RootElement("li")
class Pre : Tag("pre")

class Code() : Tag("code")
class Label() : Tag("font")
class Font() : Tag("font")
class TextArea() : Tag("textarea")


fun html(lang: String = "en", init: Html.() -> Unit): Html = Html().set("lang", lang).apply(init)
